package com.hhrpc.hhrpc.core.consumer;

import com.hhrpc.hhrpc.core.annotation.HhRpcConsumer;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.stream.Collectors;

public class ConsumerBootStrap implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    private Map<String, Object> proxyMap = new HashMap<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void screenConsumerServiceFields() throws IllegalAccessException {
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);
            //拿到bean中所有带有rpcConsumer注解的字段
            List<Field> fieldList = findServiceFields(bean.getClass());

            if (Objects.isNull(fieldList) || fieldList.size() == 0) {
                continue;
            }
            for (Field field : fieldList) {
                //用动态代理的类替换原始类
                String serviceName = field.getType().getCanonicalName();
                Object targetObj = null;
                if (proxyMap.containsKey(serviceName)) {
                    targetObj = proxyMap.get(serviceName);
                } else {
                    targetObj = createProxyObject(field.getType());
                    proxyMap.put(serviceName, targetObj);
                }
                field.setAccessible(true);
                field.set(bean, targetObj);
            }
        }
    }

    private Object createProxyObject(Class<?> clazz) {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz},
                new HhRpcConsumerInvocationHandler(clazz.getCanonicalName()));
    }


    //找到所有有加@HhRpcConsumer注解的字段
    private List<Field> findServiceFields(Class<?> clazz) {
        List<Field> result = new ArrayList<>();
        while (Objects.nonNull(clazz)) {
            List<Field> collect = Arrays.stream(clazz.getDeclaredFields())
                    .filter(field -> field.isAnnotationPresent(HhRpcConsumer.class))
                    .collect(Collectors.toList());
            if (Objects.nonNull(collect) && collect.size() > 0) {
                result.addAll(collect);
            }
            clazz=clazz.getSuperclass();
        }
        return result;
    }
}
